using System.CodeDom;

namespace ModelGenerator.RepositoryGenerator.Factories
{
    public class BetweenMethodFactory
    {
        /// <summary>
        /// Creates the method.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="propertyType">Type of the property.</param>
        /// <param name="DomainClass">The domain class.</param>
        /// <param name="isUniqueProperty">if set to <c>true</c> [is unique property].</param>
        /// <param name="isClass">if set to <c>true</c> [is class].</param>
        /// <returns></returns>
        public static CodeMemberMethod CreateMethod(string propertyName, string propertyType, string DomainClass,
                                                    bool isUniqueProperty, bool isClass)
        {
            if (propertyType == "String" || propertyType == "Boolean") return null;

            var method = new CodeMemberMethod();
            CreateMethodSignature(method, propertyName, propertyType, isUniqueProperty, DomainClass);
            if (isClass)
                CreateLikeMethodAction(method, propertyName, isUniqueProperty);
            CreateComments(propertyName, method, DomainClass, isUniqueProperty);
            return method;
        }

        /// <summary>
        /// Creates the method signature.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="propertyType">Type of the property.</param>
        /// <param name="isUniqueProperty">if set to <c>true</c> [is unique property].</param>
        /// <param name="DomainClass">The domain class.</param>
        private static void CreateMethodSignature(CodeMemberMethod method, string propertyName, string propertyType,
                                                  bool isUniqueProperty, string DomainClass)
        {
            method.Name = string.Format("FindBy{0}Between", propertyName);
            method.Parameters.Add(new CodeParameterDeclarationExpression(propertyType,
                                                                         string.Format("min{0}", propertyName)));
            method.Parameters.Add(new CodeParameterDeclarationExpression(propertyType,
                                                                         string.Format("max{0}", propertyName)));
            method.ReturnType = isUniqueProperty
                                    ? new CodeTypeReference(DomainClass)
                                    : new CodeTypeReference("IList", new CodeTypeReference(DomainClass));
        }

        /// <summary>
        /// Creates the like method action.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="isUniqueProperty">if set to <c>true</c> [is unique property].</param>
        private static void CreateLikeMethodAction(CodeMemberMethod method, string propertyName, bool isUniqueProperty)
        {
            method.Statements.Add(new CodeSnippetExpression(
                                      string.Format(
                                          "var where = CreateDetachedCriteria().Add(Expression.Between(\"{0}\", min{0}, max{0}))",
                                          propertyName)));
            method.Statements.Add(new CodeSnippetExpression(
                                      string.Format(string.Format("return Find{0}(where)",
                                                                  (isUniqueProperty) ? "First" : "All"))));
        }

        /// <summary>
        /// Creates the comments.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="method">The method.</param>
        /// <param name="DomainClass">The domain class.</param>
        /// <param name="isUniqueProperty">if set to <c>true</c> [is unique property].</param>
        private static void CreateComments(string propertyName, CodeMemberMethod method, string DomainClass,
                                           bool isUniqueProperty)
        {
            string resultTypeComment = (isUniqueProperty) ? "a" : "an IList of";
            string resultType = (isUniqueProperty) ? DomainClass : string.Format("IList<{0}>", DomainClass);

            method.Comments.Add(new CodeCommentStatement("<summary>", true));
            method.Comments.Add(
                new CodeCommentStatement(
                    string.Format("Find {0} {1} beetween two valors", resultTypeComment, DomainClass), true));
            method.Comments.Add(new CodeCommentStatement("</summary>", true));
            method.Comments.Add(
                new CodeCommentStatement(string.Format("<param name=\"min{0}\">The {0}.</param>", propertyName), true));
            method.Comments.Add(
                new CodeCommentStatement(string.Format("<param name=\"max{0}\">The {0}.</param>", propertyName), true));
            method.Comments.Add(new CodeCommentStatement(string.Format("<returns>{0}</returns>", resultType), true));
        }
    }
}